package main

import (
	"flag"
	"gitee.com/huhong/netbolt"
	"github.com/samuel/go-zookeeper/zk"
	"log"
	"strconv"
	"strings"
	"time"
	//"gitee.com/huhong/netbolt"
)

var zkConn *zk.Conn
var createCommand *string

func main() {

	createCommand = flag.String("create", "", "host1:port1:host1-myid:...:host2:port2:host2-myid") //create会重建数据,导致配置被重新加载，起到的作用目前来说可能只会修改host:port,如果错误修改myid可能会导致数据错误。如果要增加节点或者减少节点需要使用其它的方法。

	zkHost := flag.String("zkHost", "localhost:2181", "localhost:2181,nn02:2181")

	flag.Parse()

	//fmt.Println(*createCommand)

	var err error
	zkConn, _, err = zk.Connect(strings.Split(*zkHost, ","), 2000*time.Millisecond)

	defer zkConn.Close()
	if err != nil {
		log.Panic(err)
	}

	if _, err := zKCreateIfNotExist(netbolt.ZK_ROOT_PATH, []byte(""), 0, zk.WorldACL(zk.PermAll)); err != nil && err != zk.ErrNodeExists {
		log.Panic(err)
	}
	if *createCommand != "" {
		createDataNodes()
	}
}

func createDataNodes() {

	infos := strings.Split(*createCommand, ":")
	size := len(infos) / 3

	dataNodes := make([]netbolt.DataNode, size)

	splitValue := netbolt.SLOT_COUNT / uint16(size)

	//for i := 0; i < len(slotRanges); i++ {
	//	slotRanges[i].min = uint16(i) * splitValue
	//
	//	slotRanges[i].max = slotRanges[i].min + splitValue - 1
	//
	//}
	//
	//slotRanges[len(slotRanges)-1].max = maxSLOT

	exist, _, err := zkConn.Exists(netbolt.ZK_CLUSTER_PATH)
	if err != nil {
		log.Panic(err)
	}
	if exist {
		paths, _, err := zkConn.Children(netbolt.ZK_CLUSTER_PATH)
		if err != nil {
			log.Panic(err)
		}

		for _, p := range paths {

			err = zkConn.Delete(netbolt.ZK_CLUSTER_PATH+"/"+p, -1)
			if err != nil {
				log.Println(err, " ", p)
			}

		}

	} else {
		log.Panic("netbolt db server not running!")
	}

	if err != nil {
		log.Panic(err)
	}

	for i := 0; i < size; i++ {
		datas := infos[0:3]

		dataNodes[i].Min = uint16(i) * splitValue
		if i == size-1 {
			dataNodes[i].Max = netbolt.SLOT_COUNT
		} else {
			dataNodes[i].Max = dataNodes[i].Min + splitValue - 1
		}
		dataNodes[i].Host = datas[0]

		port, err := strconv.Atoi(datas[1])
		if err != nil {
			log.Panic(err)
		}
		dataNodes[i].Port = uint16(port)
		dataNodes[i].MyId = datas[2]

		if !checkNode(dataNodes[i].MyId) {
			log.Fatalf("Data Node :%s,host:%s:%d fail!", dataNodes[i].MyId, dataNodes[i].Host, dataNodes[i].Port)
		}

		buf, err := netbolt.DataSerializer.ToBytes(dataNodes[i])
		if err != nil {
			log.Panic(err)
		}
		_, err = zkConn.Create(netbolt.ZK_CLUSTER_PATH+"/"+dataNodes[i].MyId, buf, 0, zk.WorldACL(zk.PermAll))
		if err != nil {
			log.Panic(err)
		}
		log.Println("node:", dataNodes[i])
		infos = infos[3:]

	}

	paths, _, err := zkConn.Children(netbolt.ZK_CLUSTER_COMPLETE_PATH)

	if err != nil {
		log.Panic(err)
	}

	for _, path := range paths {
		zkConn.Delete(netbolt.ZK_CLUSTER_COMPLETE_PATH+"/"+path, -1)
	}
	zkConn.Create(netbolt.ZK_CLUSTER_COMPLETE_PATH+"/v", nil, zk.FlagSequence, zk.WorldACL(zk.PermAll))

}

func checkNode(myid string) bool {
	exist, _, err := zkConn.Exists(netbolt.ZK_ONLINE_PATH + "/" + myid)
	if err != nil {
		log.Panic(err)
	}

	return exist
}

func zKCreateIfNotExist(path string, data []byte, flags int32, acl []zk.ACL) (string, error) {
	if exist, _, _ := zkConn.Exists(path); !exist {
		return zkConn.Create(path, data, flags, acl)
	} else {
		return path, nil
	}
}
